package com.chuxing.security.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.chuxing.config.PermissionsState;
import com.chuxing.config.SecurityRole;
import com.chuxing.domain.DTO.*;
import com.chuxing.domain.Result;
import com.chuxing.domain.VO.GetUserInfoVO;
import com.chuxing.domain.VO.PageResultVO;
import com.chuxing.exception.GenericException;
import com.chuxing.exception.UnauthorizedException;
import com.chuxing.security.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author LiuQi
 * @create 2024-11-16-下午2:04
 */
@Tag(name = "用户服务", description = "用户服务相关接口")
@RestController()
@RequestMapping("/user")
@RequiredArgsConstructor
public class  UserController {
    private static final Logger log = LoggerFactory.getLogger(UserController.class);
    // 注入用户服务
    private final UserService userService;

    /**
     * 检查用户是否已登录
     * @return 返回一个Result对象，表示检查结果
     */
    @Operation(summary = "检查用户是否已登录", description = "检查用户是否已登录")
    @GetMapping("/isLogin")
    public Result<Object> isLogin() {
        log.info("检查用户是否已登录{}", StpUtil.getLoginIdAsString());
        // 检查用户是否已登录
        if (StpUtil.isLogin()) {
            // 如果已登录，返回成功结果，包含"已登录"消息
            return Result.success(PermissionsState.LOGGED_IN);
        }
        // 如果未登录，返回失败结果，包含"未登录"消息
        return Result.error(401, PermissionsState.NOT_LOGIN);
    }

    /**
     * 处理用户登录请求
     *
     * @param loginDTO 用户登录信息，包括用户名和密码，通过请求体传递
     * @return 返回一个Result对象，表示登录操作的结果如果登录成功，返回成功信息
     */
    @Operation(summary = "用户登录", description = "用户登录")
    @PostMapping("/login")
    public Result<Object> login(@RequestBody LoginDTO loginDTO) {
        log.info("处理用户登录请求{}", loginDTO.getUsername());
        userService.login(loginDTO);
        // 调用userService的getListOfRoles方法获取角色列表
        List<String> list = userService.getListOfRoles();
        return Result.success("登录成功",list);
    }

    /**
     * 处理用户退出操作的API接口
     *
     * @return Result对象，表示退出操作成功
     */
    @Operation(summary = "用户注销登录", description = "用户注销登录")
    @DeleteMapping("/logout")
    public Result<Object> logout() {
        log.info("处理用户退出操作{}", StpUtil.getLoginIdAsString());
        if (!StpUtil.isLogin()) {
            // 如果用户未登录，抛出异常
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        userService.logout();
        return Result.success("注销成功");
    }

    /**
     * 管理员注销用户账号
     * 主要用于账户管理，特别是在需要清理无效或违规账户时
     */
    @Operation(summary = "管理员注销用户账号", description = "管理员注销用户账号")
    @DeleteMapping("/deleteUserByAdmin/{ids}")
    public Result<Object> deleteUserByAdmin(@PathVariable List<String> ids) {
        log.info("管理员注销用户账号{}", ids);
        // 验证当前用户是否已登录
        if (!StpUtil.isLogin()) {
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 验证当前用户是否具有管理员角色
        if (!StpUtil.hasRole(SecurityRole.ROLE_ADMIN)) {
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        // 检查用户是否是管理员,不能删除管理员
        for (String id : ids) {
            // 如果是管理员且当前账户不是超级管理员，则不允许删除
            if (StpUtil.hasRole(id, SecurityRole.ROLE_ADMIN) && !StpUtil.hasRole(SecurityRole.ROLE_SUPER_ADMIN)) {
                throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
            }
            //如果删除的账户是当前账号，则不允许删除
            if (StpUtil.getLoginIdAsString().equals(id)){
                throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
            }
        }
        // 调用用户服务中的删除方法，传入用户ID列表
        userService.deleteUserByAdmin(ids);
        // 返回成功结果，表示注销操作完成
        return Result.success("注销成功");
    }

    /**
     * 处理用户注册的API接口
     *
     * @param registerDTO 包含用户信息的DTO，用于注册用户
     * @return 返回注册操作的结果，如果成功则返回成功信息
     */
    @Operation(summary = "用户注册", description = "用户注册")
    @PostMapping("/register")
    public Result<Object> register(@RequestBody RegisterDTO registerDTO) {
        log.info("处理用户注册请求{}",registerDTO.getUsername());
        userService.register(registerDTO);
        return Result.success("注册成功");
    }

    /**
     * 重置用户密码的接口方法
     *
     * @param resetPasswordDTO 包含重置密码所需信息的数据传输对象
     * @return 返回一个Result对象，表示操作结果如果密码重置成功，返回成功信息
     */
    @PutMapping("/resetPassword")
    @Operation(summary = "重置密码", description = "重置密码")
    public Result<Object> resetPassword(@RequestBody ResetPasswordDTO resetPasswordDTO) {
        log.info("处理重置密码请求{}", resetPasswordDTO.getUsername());
        // 调用userService的resetPassword方法来执行密码重置操作
        userService.resetPassword(resetPasswordDTO);
        // 返回一个表示操作成功的Result对象
        return Result.success("重置密码成功");
    }

    /**
     * 管理员修改用户信息的接口方法
     *
     * @param updateUserByAdminDTO 包含重置密码所需信息的数据传输对象
     * @return 返回一个Result对象，表示操作结果
     */
    @PutMapping("/updateUserByAdmin")
    @Operation(summary = "管理员修改用户信息", description = "管理员修改用户信息")
    public Result<Object> updateUserByAdmin(@RequestBody UpdateUserByAdminDTO updateUserByAdminDTO) {
        // 记录管理员修改用户信息的日志
        log.info("管理员修改用户信息{}", updateUserByAdminDTO);
        // 检查是否已登录
        if (!StpUtil.isLogin()){
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 检查是否具有管理员权限
        if (!StpUtil.hasRole(SecurityRole.ROLE_ADMIN)){
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        // 检查用户是否是管理员,不能修改管理员
        if (StpUtil.hasRole(updateUserByAdminDTO.getStudentId(), SecurityRole.ROLE_ADMIN) && !StpUtil.hasRole(SecurityRole.ROLE_SUPER_ADMIN)) {
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        if (updateUserByAdminDTO.getSign() >= 1) {
            // 如果是管理员，则需要检查是否是超级管理员
            if (!StpUtil.hasRole(SecurityRole.ROLE_SUPER_ADMIN)) {
                throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
            }
        }
        // 检查是否是超级管理员，并且修改的权限小于2，并且修改的不是自己
        if(StpUtil.hasRole(SecurityRole.ROLE_SUPER_ADMIN)&& updateUserByAdminDTO.getSign() <2&&
                updateUserByAdminDTO.getStudentId().equals(StpUtil.getLoginId())){
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        // 调用userService的updateUserByAdmin方法来执行用户信息修改操作
        userService.updateUserByAdmin(updateUserByAdminDTO);
        // 返回一个表示操作成功的Result对象
        return Result.success("修改成功");
    }

    /**
     * 获取用户信息
     *
     * @return 返回用户信息获取结果
     */
    @GetMapping("/getUserInfo")
    @Operation(summary = "获取用户信息", description = "获取用户信息")
    public Result<GetUserInfoVO> getUserInfo() {
        log.info("获取用户信息{}",StpUtil.getLoginIdAsString());
        // 检查用户是否已登录
        if (!StpUtil.isLogin()) {
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 获取当前登录用户的用户名
        String username = (String) StpUtil.getLoginId();
        // 调用userService的getUserInfo方法获取用户信息
        GetUserInfoVO userInfo = userService.getUserInfo(username);
        // 返回成功结果，包含用户信息
        return Result.success("获取用户信息成功", userInfo);
    }

    /**
     * 更新用户信息
     *
     * @param userInfoDTO 包含用户信息的数据传输对象
     */
    @PostMapping("/saveUserInfo")
    @Operation(summary = "更新用户信息", description = "更新用户信息")
    public Result<Object> saveUserInfo(@RequestBody UserInfoDTO userInfoDTO) {
        log.info("处理更新用户信息请求{}", userInfoDTO);
        // 检查用户是否已登录
        if (!StpUtil.isLogin()) {
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 获取当前登录用户的用户名
        String username = (String) StpUtil.getLoginId();
        // 设置用户ID
        userInfoDTO.setStudentId(username);
        // 调用userService的saveUserInfo方法更新用户信息
        userService.saveUserInfo(userInfoDTO);
        // 返回成功结果，表示更新成功
        return Result.success("更新用户信息成功");
    }

    /**
     * 通过用户ID获取用户信息的接口
     * 此接口用于根据特定的用户ID查询并返回用户信息
     */
    @GetMapping("/getUserById/{id}")
    @Operation(summary = "管理员根据ID获取用户信息", description = "管理员根据ID获取用户信息")
    public Result<GetUserInfoVO> getUserById(@PathVariable String id) {
        log.info("根据ID获取用户信息，参数为：{}", id);
        // 检查用户是否已登录
        if (!StpUtil.isLogin()) {
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 检查用户是否具有管理员角色
        if (!StpUtil.hasRole(SecurityRole.ROLE_ADMIN)) {
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        // 调用userService的getById方法根据ID获取用户信息
        GetUserInfoVO user = userService.getUserById(id);
        // 返回成功结果，包含用户信息
        return Result.success("获取用户信息成功", user);
    }

    /**
     * 分页查询用户信息的接口
     * 此接口用于根据分页参数查询用户信息
     */
    @PostMapping("/getUserList")
    @Operation(summary = "管理员分页查询用户信息", description = "管理员分页查询用户信息")
    public Result<PageResultVO> getUserList(@RequestBody GetUserListDTO getUserListDTO) {
        log.info("分页查询用户信息，参数为：{}", getUserListDTO);
        // 检查用户是否已登录
        if (!StpUtil.isLogin()) {
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 检查用户是否具有管理员角色
        if (!StpUtil.hasRole(SecurityRole.ROLE_ADMIN)) {
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        PageResultVO pageResultVO = userService.getUserList(getUserListDTO);
        return Result.success("获取用户列表成功", pageResultVO);
    }

    /**
     * 管理员添加用户的接口
     * 此接口用于管理员添加新用户
     */
    @PostMapping("/addUserByAdmin")
    @Operation(summary = "管理员添加用户", description = "管理员添加用户")
    public Result<Object> addUserByAdmin(@RequestBody AddUserByAdminDTO addUserByAdminDTO) {
        log.info("管理员添加用户，参数为：{}", addUserByAdminDTO);
        // 检查是否已登录
        if(!StpUtil.isLogin()){
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        // 检查是否具有管理员权限
        if(!StpUtil.hasRole(SecurityRole.ROLE_ADMIN)){
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        // 判断是否是超级管理员，如果不是则抛出异常
        if(addUserByAdminDTO.getSign()>=1&&!StpUtil.hasRole(SecurityRole.ROLE_SUPER_ADMIN)){
            throw new GenericException(PermissionsState.PERMISSION_NOT_ENOUGH);
        }
        userService.addUserByAdmin(addUserByAdminDTO);
        return Result.success("添加用户成功");
    }

    /**
     * 修改密码的接口
     * 此接口用于修改用户密码
     */
    @PostMapping("/changePassword")
    @Operation(summary = "修改密码", description = "修改密码")
    public Result<Object> changePassword(@RequestBody ChangePasswordDTO changePasswordDTO) {
        log.info("修改密码，参数为：{}", changePasswordDTO);
        // 检查用户是否已登录
        if (!StpUtil.isLogin()) {
            throw new UnauthorizedException(PermissionsState.NOT_LOGIN);
        }
        userService.changePassword(changePasswordDTO);
        return Result.success("修改密码成功");
    }
}
